# get window app handle by window title
# pip install pywin32
# pip install pyautogui
import shutil
import tk
import win32gui,sys
import pyautogui
import os,threading
import cv2
import numpy as np
import time
import random
# from PIL import Image, ImageTk

try:
    from enhanced_matcher import improved_find_image_from_image, WoWImageMatcher
    ENHANCED_MATCHING = True
    print("加载增强图像匹配功能")
except ImportError:
    ENHANCED_MATCHING = False
    print("使用基础图像匹配功能")

def get_app_dir():
    base_ext = os.path.splitext(os.path.basename(sys.argv[0]))[1]
    # print("argv:",sys.argv)
    app_dir=""
    if base_ext == '.exe':
        # Nuitka 打包或 PyInstaller 打包
        # if hasattr(sys, '_MEIPASS'):
        #     # Nuitka 单文件模式
        #     return sys._MEIPASS
        app_dir= os.path.dirname(sys.argv[0])
    else:
        app_dir= os.path.dirname(os.path.abspath(__file__))
    # os.chdir(app_dir)
    # print("应用目录:",app_dir)
        if app_dir not in sys.path:
            sys.path.append(app_dir)
    # print("sys.path:",sys.path)
    os.chdir(app_dir)
    return app_dir
rundir=get_app_dir()
tmpdir=os.path.join(rundir,'tmp')
if not os.path.exists(tmpdir):
    os.makedirs(tmpdir)
# get user path
user_dir = os.path.expanduser('~')
app_dir = os.path.dirname(os.path.abspath(__file__))
app_tmpdir=os.path.join(app_dir,'tmp')
print("应用目录:",app_dir)
print('用户目录:',user_dir)
print('执行目录:',rundir)
print('临时目录:',tmpdir)
move_images=[
    'fish.png',
    'fishing.png',
    'fish_buff.png'
]
# print("移动图片:",move_images)
for image in move_images:
    src_image=os.path.join(app_tmpdir,image)
    if os.path.exists(src_image) and not os.path.exists(os.path.join(tmpdir, image)):
        shutil.copy(src_image, os.path.join(tmpdir, image))
        print(f"移动图片: {src_image} 到 {tmpdir}")

fish_image=os.path.join(tmpdir,'fish.png')
fishing_image=os.path.join(tmpdir,'fishing.png')
fish_buff_image=os.path.join(tmpdir,'fish_buff.png')



fish_event=threading.Event()

class AutoFish:
    def __init__(self):
        self.fish_image = fish_image
        self.fishing_image = fishing_image
        self.fish_buff_image = fish_buff_image
        self.fish_event = fish_event
        self.fish_buff_enable=False
        self.fish_buff_set_delay =10 #分钟
        self.fish_end_timeout = 15 #秒
        self.debug = False

def get_app_handle_by_title(title):
    return win32gui.FindWindow(None, title) # get window app handle by window title
# list mathces window title
def list_all_app():
    def callback(handle, handles):
        handles.append(handle)
        return True
    handles = []
    win32gui.EnumWindows(callback, handles)
    return [(handle, win32gui.GetWindowText(handle)) for handle in handles]
def list_app_handle_by_title(title):
    # pattern=re.RegexFlag(title)
    def callback(handle, handles):
        handles.append(handle)
        return True
    handles = []
    win32gui.EnumWindows(callback, handles)
    return [(handle, win32gui.GetWindowText(handle)) for handle in handles if title in win32gui.GetWindowText(handle)]
def get_window_handle(window_name):
    hwnd = win32gui.FindWindow(None, window_name)
    return hwnd
def get_window_info(window_name):
    hwnd = win32gui.FindWindow(None, window_name)
    if hwnd:
        rect = win32gui.GetWindowRect(hwnd)
        left, top, right, bottom = rect
        center_x = (left + right) // 2
        center_y = (top + bottom) // 2
        width = right - left
        height = bottom - top
        return rect, [center_x, center_y], [width, height]
    return None, None, None 
def wow_window():
    res=list_app_handle_by_title("魔兽世界")
    app=res[0]
    hwnd = win32gui.FindWindow(None, app[1])
    rect=None
    if hwnd:
        rect, [center_x, center_y], [width, height]= get_window_info(app[1])
        print("App",app[1])
        image = pyautogui.screenshot(region=(rect[0]+7, rect[1]+31, width-12, height-40))
        # image = pyautogui.screenshot(region=(0, 0, 800, 600))
        #包含透明通道的图片
        # image = pyautogui.screenshot(region=(0, 0, 800, 600))
        image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
        cv2.imwrite(os.path.join(tmpdir, 'app.jpg'), image)
        # bgr to rgb
        
        # cv2.imshow("app",image)
        # cv2.moveWindow('image', 100, 100)
        # cv2.waitKey(0)
def find_image_from_image(image,frame,threshold=0.5,wait='',method='adaptive'):
    """
    改进的图像查找函数 - 支持多种高精度算法
    """
    if ENHANCED_MATCHING:
        # 使用增强匹配器
        center, confidence, info = improved_find_image_from_image(image, frame, threshold, method)
        res_image = None
        
        # 绘制检测结果
        box=None
        if center is not None:
            x, y = center
            h, w = image.shape[:2] if hasattr(image, 'shape') else (20, 20)
            box = (x-w//2, y-h//2, x+w//2, y+h//2)
            # cv2.rectangle(frame, (x-w//2, y-h//2), (x+w//2, y+h//2), (0, 255, 0), 2)
            # cv2.circle(frame, (x, y), 5, (0, 255, 0), -1)
            # 提取匹配区域
            res_image = frame[max(0, y-h//2):y+h//2, max(0, x-w//2):x+w//2]

        
        # cv2.putText(frame, f"Conf:{confidence:.3f} {info}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
        return center, res_image, confidence,box
    else:
        # 使用原始模板匹配方法
        # ...existing template matching code...
        if len(image.shape) == 3 and image.shape[2]!=1:
            image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 
        frme_image = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        result = cv2.matchTemplate(frme_image, image, cv2.TM_CCOEFF_NORMED)
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
        
        res=None
        center=None
        res_image=None
        cv2.rectangle(frame, max_loc, (max_loc[0] + image.shape[1], max_loc[1] + image.shape[0]), (0, 255, 0), 2)
        cv2.putText(frame, f"max_val:{max_val}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 1)
        if max_val>threshold:
            x1,y1=max_loc
            res_image=frme_image[max_loc[1]:max_loc[1]+image.shape[0],max_loc[0]:max_loc[0]+image.shape[1]]
            center=[int(x1+image.shape[1]/2),int(y1+image.shape[0]/2)]
            res=max_loc
        return center,res_image,max_val
def mouse_click(x, y, duration=0.1,type='left'):
    try:
        point=pyautogui.position()
        pyautogui.moveTo(x, y)
        time.sleep(duration)
        if type=='left':
            pyautogui.click(button='left')
        else:
            pyautogui.click(button='right')
        time.sleep(duration)
        pyautogui.moveTo(point.x, point.y)
    except Exception as e:
        print(f"❌ 鼠标点击失败: {e}")
        return False
    time.sleep(.3)
def fish_track(args:AutoFish):
    # model=YOLO("./datasets/wow_fish.v2i.yolov11/best.pt")
    target_window_title = "魔兽世界"
    fish_image = args.fish_image
    fishing_image = args.fishing_image
    fish_buff_image = args.fish_buff_image
    debug = args.debug
    event = args.fish_event
    res=list_app_handle_by_title(target_window_title)
    if len(res)==0:
        raise Exception("没有找到魔兽世界")
    from wow_out_audio import ApplicationSoundCapture
    audio_capture = ApplicationSoundCapture()
    audio_capture.volume_threshold = 0.01  # 设置音量阈值
    
    
    
    app=res[0]
    hwnd = win32gui.FindWindow(None, app[1])
    rect=None
    if hwnd:
        rect, [center_x, center_y], [width, height]= get_window_info(app[1])
        print("魔兽程序窗口信息:", rect, [center_x, center_y], [width, height])
        region=(rect[0]+7, rect[1]+31, width-12, height-40)
        
        # 获取屏幕截图
        image = pyautogui.screenshot(region=region)
        app_image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)

        
        # fishend=["fishing_end.png","fishing_end1.png","fishing_end2.png","fishing_end3.png"]
        # sift_matcher_image(image1, image2)
        # app_image = cv2.imread(image1)
        fish_image_data = cv2.imread(fish_image)
        fishing_image_data = cv2.imread(fishing_image)
        fish_buff_image_data = None
        # fishend_images=[cv2.imread(os.path.join(tmpdir,f)) for f in fishend]
        # fishend_images_len=len(fishend_images)

        timecost=0
        timestart=time.time()
        fishend_event=False
        fishing_res=None
        fishing_time=0
        fishing_track=0
        fishend_track=0
        fish_conf=0.6
        fishing_conf=0.6
        fishing_conf_cache=[]
        fishing_status_box=[]
        finhing_box=None
        fishing_res=None
        max_volume=0.0
        # 上钩音量是平均值的倍率
        # fish_volume_threshold=3
        avg_volumes=[]
        fish_state="fishstart"
        fish_buff_position=None
        fish_buff_box=None
        fish_buff_time=0
        image = pyautogui.screenshot(region=region)
        app_image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)

        if args.fish_buff_enable:
            fish_buff_image_data = cv2.imread(fish_buff_image)
            center,_,track_max,box=find_image_from_image(fish_buff_image_data,app_image,fish_conf)
            if center is not None:
                fish_buff_position=center
                fish_buff_box=box
                fish_buff_time=time.time()
                print(f"🐟 检测到鱼饵图片位置: {fish_buff_position}, 盒子: {fish_buff_box}")
            else:
                print("❌ 未检测到鱼饵图片:")
                raise Exception("未检测到鱼饵图片,请检查图片")
            
        
        fish_bt_center,_,track_max,fish_bt_box=find_image_from_image(fish_image_data,app_image,fish_conf)
        if fish_bt_center is None:
            print("❌ 未检测到鱼竿图片:")
            raise Exception("未检测到鱼竿图片,请检查图片")
        else:
            print(f"🎯 检测到鱼竿图片位置: {fish_bt_center}, 盒子: {fish_bt_box}")
        # 列出可用设备
        devices = audio_capture.list_loopback_devices()
        def audio_detected(volume, audio_data):
            # print(f"🔊 检测到音频: 音量 {volume:.3f}")
            pass
        if devices:
            # 使用第一个找到的环回设备
            device_index = devices[0][0]
            
            if audio_capture.capture_system_audio(device_index, audio_detected):
                print("🔊 成功启动音频捕获")
            else:
                print("❌ 音频捕获启动失败")
                raise Exception("音频捕获启动失败")
        else:
            print("❌ 没有找到可用的环回设备")
            raise Exception("没有找到可用的环回设备:请检查音频设置,可能是音频设备未正确配置")
        fish_volume=0.05
        while True:
            if event.is_set():
                print("钓鱼线程结束")
                audio_capture.stop_capture()
                break
            image = pyautogui.screenshot(region=region)
            app_image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
            timecost=round(time.time()-timestart,3)
            cv2.putText(app_image, f"Time:{timecost}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 1)
            # fish_volume=0.05
            if args.fish_buff_enable and fish_buff_position is not None and fish_buff_time< time.time():
                print(f"开始上鱼饵:")
                mouse_click(fish_buff_position[0]+region[0],fish_buff_position[1]+region[1])
                time.sleep(3)
                fish_buff_time=time.time()+ args.fish_buff_set_delay
                fish_state="fishstart"
                pass
            if fish_buff_box is not None and fish_buff_time>0:
                cv2.rectangle(app_image, (fish_buff_box[0], fish_buff_box[1]), (fish_buff_box[2], fish_buff_box[3]), (0, 255, 0), 2)
                cv2.putText(app_image, f"buff:{round(fish_buff_time-time.time(),1)}s", (fish_buff_box[0], fish_buff_box[1]-10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 1)
            cv2.rectangle(app_image, (fish_bt_box[0], fish_bt_box[1]), (fish_bt_box[2], fish_bt_box[3]), (0, 255, 0), 2)
            match fish_state:
                case "fishstart":
                    fishing_status_box=[]
                    max_volume = 0.0
                    mouse_click(fish_bt_center[0]+region[0],fish_bt_center[1]+region[1])
                    fish_state="fishing"
                    print("开始钓鱼")
                    time.sleep(1.5)
                    fishing_time=time.time()
                    # time.sleep(random.uniform(1.5, 2.5))
                    
                    pass
                case "fishing":
                    # print("钓鱼中,检测鱼饵")
                    fishing_res,_,track_max,box=find_image_from_image(fishing_image_data,app_image,fishing_conf,method='template')
                    fishing_conf_cache.insert(0,track_max)
                    fishing_conf_cache.sort(reverse=True)
                    fishing_conf_cache=fishing_conf_cache[:3]
                    if fishing_res is not None:
                        fish_state="fishend"
                        fishing_status_box.append(box)
                        # box 扩展10像素
                        x1, y1, x2, y2 = box
                        x1 = max(0, x1 - 10)
                        x2 = min(app_image.shape[1], x2 + 10)
                        y1 = max(0, y1 - 10)
                        y2 = min(app_image.shape[0], y2 + 10)
                        finhing_box= (x1, y1, x2, y2)
                        print("检测到鱼饵",fishing_res)
                    else:
                        fishing_track=round(time.time()-fishing_time,3)
                        print( "鱼饵检测失败,耗时:",fishing_track,fishing_conf,fishing_conf_cache)
                        fishing_conf=fishing_conf_cache.pop(0)
                        fishing_conf=fishing_conf-0.05
                        if fishing_track>5:
                            print( "鱼饵检测失败 超时,重置钓鱼:")
                            fish_state="fishstart"
                        time.sleep(2)
                    time.sleep(.1)
                    pass
                case "fishend":
                    current_volume = audio_capture.get_current_volume()
                    max_volume= max(max_volume, current_volume)
                    fishend_track=round(time.time()-fishing_time,3)
                    if finhing_box is not None:
                        # 画图
                        cv2.rectangle(app_image, (finhing_box[0], finhing_box[1]), (finhing_box[2], finhing_box[3]), (0, 255, 0), 2)
                    # emoji 图标 喇叭

                    if current_volume > 0.01:
                        print(f"\r🔊 当前音量: {current_volume:.3f}/{fish_volume:.3f}, 钓鱼时间: {fishend_track:.1f}s")
                    else:
                        print(f"\r🔇 当前音量: {current_volume:.3f}/{fish_volume:.3f}, 钓鱼时间: {fishend_track:.1f}s",end="")

                    if current_volume > fish_volume:
                        if fishend_track<1.5:
                            print("❌ 异常钓鱼结束,触发音量:",current_volume)
                            fish_volume=0.05
                        else:
                            pass
                        fish_state="fishstart"
                        print(f"🐳 钓鱼成功,触发音量:{fish_volume:.3f},实际音量:{current_volume:.3f}")
                        mouse_click(fishing_res[0]+region[0],fishing_res[1]+region[1],type='right')
                        time.sleep(1)
                    if fishend_track>args.fish_end_timeout:
                        print(f"\r⏰ 钓鱼超时,阈值:{fish_volume:.3f},超时最大音量:{max_volume:.3f}")
                        if max_volume>0.01:
                            print(f"🔄 更新阈值:{fish_volume:.3f} -> {max_volume*0.8:.3f}")
                            fish_volume=max_volume*0.8
                        fish_state="fishstart"
                        time.sleep(2)
                    time.sleep(0.1)
                    pass
            if debug:
                cv2.imshow('app_image', cv2.resize(app_image, (800, 600)))
                cv2.moveWindow('app_image', 0, 0)
            # if len(fishing_status_box)>0:
            #     # 提取区域尺寸不同的图片合并成一张大图
            #     fishing_images = processor.collect_fishing_images(app_image, fishing_status_box)
            #     if fishing_images:
            #         big_image = processor.safe_concatenate_images(fishing_images, axis=1)
            #         if big_image is not None:
            #             cv2.imshow('fishing_images', big_image)
            #             cv2.moveWindow('fishing_images', 0, app_image.shape[0])
            key = cv2.waitKey(1)  # 等待 1 毫秒，监听按键

            # 监听按键
            if key == ord('q'):
                print("按下了 'q' 键，退出程序")
                fishend_event=True
                break
            # print("timecost:",timecost)
            if fishend_event:
                break
            # time.sleep(10)
            pass
        if debug:
            cv2.destroyAllWindows()
        if audio_capture:
            audio_capture.stop_capture()
        print("钓鱼线程结束")
    pass
def thread_fish_track(args:AutoFish,endcb=None):
    global is_fishing
    try:
        args.fish_event.clear()  # 清除事件标志
        fish_track(args)
    except Exception as e:
        print(f"❌ 启动钓鱼失败: {e}")
        # msg = f"❌ 启动钓鱼线程失败: {e}"
        # tk.messagebox.showerror("错误", msg)
    finally:
        pass
    print("钓鱼线程已结束")
    if endcb:
        endcb()

def fish_gui():
    """
    钓鱼GUI界面
    """
    import tkinter as tk
    from tkinter import filedialog, messagebox
    # 获取应用运行目录
    from tk_image_input import EnhancedImageSelector
    global fish_image, fishing_image,fish_buff_image
    root = tk.Tk()
    root.title("自动钓鱼懒人助手")
    root.geometry("700x800")
    
    # 创建两个图片选择器
    image_size= (40, 40)  # 设置图片选择器的大小
    selector1 = EnhancedImageSelector(root, "钓鱼按钮图片:",fish_image,preview_size=image_size)
    selector2 = EnhancedImageSelector(root, "鱼鳔图片:", fishing_image,preview_size=image_size)
    selector3 = EnhancedImageSelector(root, "鱼饵图片:", fish_buff_image,preview_size=image_size)
    # 鱼饵周期 单位分钟,添加一个int 类型输入框
    
    buff_frame = tk.Frame(root)
    buff_frame.pack(fill=tk.X,padx=10)
    fish_buff_set_delay = tk.IntVar(value=10)  # 默认10分钟
    fish_buff_enable = tk.BooleanVar(value=True)  # 默认不启用鱼饵 
    # fish_buff_set_delay = 10  # 默认10分钟
    # 添加鱼饵周期输入框
    fish_buff_label = tk.Label(buff_frame, text="鱼饵周期 (分):", bg="lightblue")
    fish_buff_label.pack(side=tk.LEFT, padx=10)

    fish_buff_entry = tk.Entry(buff_frame, textvariable=fish_buff_set_delay, bg="white",width=5)
    fish_buff_entry.pack(side=tk.LEFT, padx=10)

    # 添加鱼饵启用复选框
    fish_buff_checkbox = tk.Checkbutton(
        buff_frame, 
        text="启用鱼饵", 
        variable=fish_buff_enable,
        bg="lightblue"
    )
    fish_buff_checkbox.pack(side=tk.LEFT, padx=10)

    def start_fishing():
        # 启动钓鱼线程
        global fish_image, fishing_image,fish_buff_image_new,is_fishing
        try:
            start_button.config(state=tk.DISABLED, text="启动中...")
            fish_image_new = os.path.abspath(selector1.get_image_path())
            fishing_image_new = os.path.abspath(selector2.get_image_path())
            fish_buff_image_new = os.path.abspath(selector3.get_image_path())

            if fish_image_new != fish_image:
                shutil.copy(fish_image_new, fish_image)
                selector2.set_image_path(fish_image)
            if fishing_image_new != fishing_image:
                # 更新图片路径
                shutil.copy(fishing_image_new, fishing_image)
                selector2.set_image_path(fishing_image)
            if fish_buff_image_new != fish_buff_image:
                shutil.copy(fish_buff_image_new, fish_buff_image)
                selector3.set_image_path(fish_buff_image)
            debug=debug_var.get()
            if not os.path.exists(fish_image) or not os.path.exists(fishing_image):
                messagebox.showerror("错误", "请确保钓鱼按钮和鱼鳔图片存在")
                return
            print(f"钓鱼按钮图片: {fish_image}")
            print(f"鱼鳔图片: {fishing_image}")
            print(f"调试模式: {debug}")
            args= AutoFish()
            args.fish_image = fish_image
            args.fishing_image = fishing_image
            args.fish_buff_image = fish_buff_image
            args.fish_buff_enable = fish_buff_enable.get()
            args.fish_buff_set_delay = fish_buff_set_delay.get() * 60  #分钟转换为秒
            args.fish_end_timeout = int(fish_end_timeout_entry.get())  # 获取钓鱼超时设置
            if args.fish_buff_image and os.path.exists(args.fish_buff_image):
                print(f"鱼饵图片: {args.fish_buff_image}")
            if args.fish_buff_set_delay> 0 and args.fish_buff_enable:
                print(f"鱼饵启用: {args.fish_buff_enable}, 鱼饵周期: {args.fish_buff_set_delay}秒")
            else:
                args.fish_buff_enable = False
                print("鱼饵未启用")
            
            args.fish_event = fish_event
            args.debug = debug
            print(f"调试模式: {debug}")
            fishing_thread = threading.Thread(target=thread_fish_track, args=(args,stop_fishing))
            fishing_thread.start()
            start_button.pack_forget()  # 隐藏开始按钮
            stop_button.pack(side=tk.LEFT, padx=20, pady=10)  # 显示停止按钮
        except Exception as e:
            print(f"❌ 启动钓鱼线程失败: {e}")
            stop_fishing()
            fish_event.clear()  # 清除事件标志
            messagebox.showerror("错误", f"启动钓鱼线程失败: {str(e)}")
        finally:
            print("钓鱼结束")
        # 禁用开始按钮
        # start_button.config(state=tk.DISABLED)
    def stop_fishing():
        print("停止钓鱼")
        fish_event.set()
        stop_button.pack_forget()  # 隐藏停止按钮
        start_button.pack(side=tk.LEFT, padx=20, pady=10)  # 显示开始按钮
        start_button.config(state=tk.NORMAL, text="开始钓鱼")

    # 测试按钮
    def test_get_paths():
        print(f"图片1: {selector1.get_image_path()}")
        print(f"图片2: {selector2.get_image_path()}")
        print(f"图片1有效: {selector1.is_valid()}")
        print(f"图片2有效: {selector2.is_valid()}")
    
    # 添加一个备注信息,左对齐
    desc="""
钓鱼准备工作:
1. 魔兽窗口最佳控制在1200,或者1500宽度左右
2. 第一人称视角最佳
3. 脱出钓鱼技能放在当前可视位置可点击,关闭UI缩放.让图标够大容易识别
4. 自动钓鱼期间会控制鼠标移动右键点击,请不要手动操作鼠标
5. 需要开启魔兽世界的音频输出,只保留游戏钓鱼音效,并且音量足够大,可以听到上钩音效
6. 如果没有检测到钓鱼按钮,请检查相关图片是否正确
7. 如果没有检测到鱼饵,请检查相关图片是否正确
8. 如果钓鱼过程中出现异常,请检查魔兽世界的音频设置,可能是音频设备未正确配置
9. 按q键可以退出钓鱼

关注命令行日志,可以看到钓鱼状态和音频检测信息
"""
    attr_frame = tk.Frame(root)
    attr_frame.pack(fill=tk.X, padx=10, pady=10)
    # 钓鱼超时
    fish_end_timeout_label = tk.Label(attr_frame, text="钓鱼超时 (秒):", bg="lightblue")
    fish_end_timeout_label.pack(side=tk.LEFT, padx=10)
    fish_end_timeout_entry = tk.Entry(attr_frame, width=5)
    fish_end_timeout_entry.insert(0, "15")
    fish_end_timeout_entry.pack(side=tk.LEFT, padx=10)

    debug_var = tk.BooleanVar()
    debug_var.set(True)  # 默认不启用调试模式
    debug_checkbox = tk.Checkbutton(attr_frame, text="启用调试模式", variable=debug_var,bg="lightblue")
    debug_checkbox.pack(side=tk.LEFT, padx=10, pady=10)

    info_frame = tk.Frame(root)
    info_frame.pack(fill=tk.X,padx=10)
    info_label = tk.Label(info_frame, text=desc, anchor="w", justify="left",  font=("Arial", 10))
    info_label.pack(fill=tk.X, padx=10)
    # 创建 开始钓鱼按钮,停止钓鱼按钮,多选框debug 同一行
    start_button = tk.Button(root, text="开始钓鱼", command=start_fishing)
    start_button.pack(side=tk.LEFT, padx=20, pady=10)

    stop_button = tk.Button(root, text="停止钓鱼", command=stop_fishing)
    stop_button.pack(side=tk.LEFT, padx=20, pady=10)
    # 不可见
    stop_button.pack_forget()
    # 可见
    # stop_button.pack(side=tk.LEFT, padx=10, pady=10)
    
    # 测试按钮
    # test_button = tk.Button(root, text="获取路径", command=test_get_paths)
    # test_button.pack(pady=20)
    
    root.mainloop()
if __name__=="__main__":
    fish_event = threading.Event()
    # fish_track(fish_event)
    fish_gui()

# 打包 额外添加tmp目录及以下所有文件

# python -m nuitka --onefile --include-data-dir=tmp=tmp --enable-plugin=tk-inter autofish.py 
# python -m nuitka --onefile --windows-disable-console --enable-plugin=numpy script.py